﻿using System;
using System.Collections;
using System.Management;
using System.Windows.Forms;
using Microsoft.Win32;

namespace SwitchNet
{
    class NetworkManagement
    {
        #region set Methods

        #region public set Methods

        public static void SetIPAddress(NICProfile nicProfile)
        {
            SetIP(nicProfile.Name, nicProfile.IP, nicProfile.Subnet);
            SetGateway(nicProfile.Name, nicProfile.Gateway);
            SetDNS(nicProfile.Name, nicProfile.DNSPreferred, nicProfile.DNSAltermate);
        }

        public static void SetMACAddress(NICProfile nicProfile)
        {
            string DriverDesc = null;
            int nicNameLength = nicProfile.Name.Length;

            int firstSpace = nicProfile.Name.IndexOf(' ');

            DriverDesc = nicProfile.Name.Substring(firstSpace + 1);

            string MACAddress = nicProfile.MAC.Replace(":", "");

            UserRegistrySetMACAddress(DriverDesc, MACAddress);
        }

        private static void UserRegistrySetMACAddress(string DriverDesc, string MACAddress)
        {
            RegistryKey nicSet = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}", true);

            string[] nicNames = nicSet.GetSubKeyNames();
            for (int i = 0; i < nicSet.SubKeyCount; i++)
            {
                RegistryKey nic = nicSet.OpenSubKey(nicNames[i], true);

                foreach (string valueName in nic.GetValueNames())
                {
                    if (valueName.Equals("DriverDesc"))
                    {
                        string name = nic.GetValue("DriverDesc").ToString();
                        if (DriverDesc.Equals(name))
                        {
                            nic.SetValue("NetworkAddress", MACAddress);
                            nic.Flush();
                            nic.Close();

                            break;
                        }
                    }
                }
            }

            nicSet.Close();
        }
        /// <summary>
        /// Set's WINS of the local machine
        /// </summary>
        /// <param name="NIC">NIC Address</param>
        /// <param name="priWINS">Primary WINS server address</param>
        /// <param name="secWINS">Secondary WINS server address</param>
        /// <remarks>Requires a reference to the System.Management namespace</remarks>
        public static void setWINS(string NIC, string priWINS, string secWINS)
        {
            ManagementClass objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection objMOC = objMC.GetInstances();

            foreach (ManagementObject objMO in objMOC)
            {
                if ((bool)objMO["IPEnabled"])
                {
                    if (objMO["Caption"].Equals(NIC))
                    {
                        try
                        {
                            ManagementBaseObject setWINS;
                            ManagementBaseObject wins =
                            objMO.GetMethodParameters("SetWINSServer");
                            wins.SetPropertyValue("WINSPrimaryServer", priWINS);
                            wins.SetPropertyValue("WINSSecondaryServer", secWINS);

                            setWINS = objMO.InvokeMethod("SetWINSServer", wins, null);
                        }
                        catch (Exception)
                        {
                            throw;
                        }
                    }
                }
            }
        }

        public static void SetDHCP(string nicName)
        {
            ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection moc = mc.GetInstances();

            foreach (ManagementObject mo in moc)
            {
                // Make sure this is a IP enabled device. Not something like memory card or VM Ware
                if ((bool)mo["IPEnabled"])
                {
                    if (mo["Caption"].Equals(nicName))
                    {
                        try
                        {
                            ManagementBaseObject newDNS = mo.GetMethodParameters("SetDNSServerSearchOrder");
                            newDNS["DNSServerSearchOrder"] = null;
                            ManagementBaseObject enableDHCP = mo.InvokeMethod("EnableDHCP", null, null);
                            ManagementBaseObject setDNS = mo.InvokeMethod("SetDNSServerSearchOrder", newDNS, null);
                        }
                        catch (Exception)
                        {
                            throw;
                        }
                    }
                }
            }
        }

        #endregion

        #region private static set Methods

        /// <summary>
        /// Set's a new IP Address and it's Submask of the local machine
        /// </summary>
        /// <param name="ip_address">The IP Address</param>
        /// <param name="subnet_mask">The Submask IP Address</param>
        /// <remarks>Requires a reference to the System.Management namespace</remarks>
        private static void SetIP(string NIC, string ip_address, string subnet_mask)
        {
            ManagementClass objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection objMOC = objMC.GetInstances();

            foreach (ManagementObject objMO in objMOC)
            {
                if ((bool)objMO["IPEnabled"])
                {
                    if (objMO["Caption"].Equals(NIC))
                    {
                        try
                        {
                            ManagementBaseObject setIP;
                            ManagementBaseObject newIP =
                                objMO.GetMethodParameters("EnableStatic");

                            newIP["IPAddress"] = new string[] { ip_address };
                            newIP["SubnetMask"] = new string[] { subnet_mask };

                            setIP = objMO.InvokeMethod("EnableStatic", newIP, null);
                        }
                        catch (Exception)
                        {
                            throw;
                        }

                    }
                }
            }
        }

        /// <summary>
        /// Set's a new Gateway address of the local machine
        /// </summary>
        /// <param name="gateway">The Gateway IP Address</param>
        /// <remarks>Requires a reference to the System.Management namespace</remarks>
        private static void SetGateway(string NIC, string gateway)
        {
            ManagementClass objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection objMOC = objMC.GetInstances();

            foreach (ManagementObject objMO in objMOC)
            {
                if ((bool)objMO["IPEnabled"])
                {
                    if (objMO["Caption"].Equals(NIC))
                    {
                        try
                        {
                            ManagementBaseObject setGateway;
                            ManagementBaseObject newGateway =
                                objMO.GetMethodParameters("SetGateways");

                            newGateway["DefaultIPGateway"] = new string[] { gateway };
                            newGateway["GatewayCostMetric"] = new int[] { 1 };

                            setGateway = objMO.InvokeMethod("SetGateways", newGateway, null);
                        }
                        catch (Exception)
                        {
                            throw;
                        }

                        break;
                    }
                }
            }
        }

        private static void SetDNS(string NIC, string DNSPreferred, string DNSAltermate)
        {
            ManagementClass objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection objMOC = objMC.GetInstances();

            foreach (ManagementObject objMO in objMOC)
            {
                if ((bool)objMO["IPEnabled"])
                {
                    if (objMO["Caption"].Equals(NIC))
                    {
                        try
                        {
                            ManagementBaseObject newDNS =
                                objMO.GetMethodParameters("SetDNSServerSearchOrder");

                            string[] DNSServerSearchOrder = new string[] {DNSPreferred, DNSAltermate};

                            newDNS["DNSServerSearchOrder"] = DNSServerSearchOrder;
                            ManagementBaseObject setDNS = 
                                objMO.InvokeMethod("SetDNSServerSearchOrder", newDNS, null);
                        }
                        catch (Exception e)
                        {
                            MessageBox.Show("Error" + e.Message);
                        }
                    }
                }
            }
        }

        #endregion

        #endregion

        #region public static get Methods

        /// <summary>
        /// Returns the network card configuration of the specified NIC
        /// </summary>
        /// <param name="nicName">Name of the NIC</param>
        /// <param name="ipAdresses">Array of IP</param>
        /// <param name="subnets">Array of subnet masks</param>
        /// <param name="gateways">Array of gateways</param>
        /// <param name="dnses">Array of DNS IP</param>
        public static void GetIP(string nicName, out string[] ipAdresses, out string[] subnets, out string[] gateways, out string[] dnses)
        {
            ipAdresses = null;
            subnets = null;
            gateways = null;
            dnses = null;

            ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection moc = mc.GetInstances();

            foreach (ManagementObject mo in moc)
            {
                // Make sure this is a IP enabled device. Not something like memory card or VM Ware
                if ((bool)mo["ipEnabled"])
                {
                    if (mo["Caption"].Equals(nicName))
                    {
                        ipAdresses = (string[])mo["IPAddress"];
                        subnets = (string[])mo["IPSubnet"];
                        gateways = (string[])mo["DefaultIPGateway"];
                        dnses = (string[])mo["DNSServerSearchOrder"];

                        break;
                    }
                }
            }
        }

        /// <summary>
        /// Get the IP Address of nicName
        /// </summary>
        /// <param name="nicName">Name of the NIC</param>
        /// <param name="IPAddress">IP</param>
        /// <returns></returns>
        public static string[] GetIPAddress(string nicName)
        {
            string[] IPAddress = null;

            ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection moc = mc.GetInstances();

            foreach (ManagementObject mo in moc)
            {
                // Make sure this is a IP enabled device. Not something like memory card or VM Ware
                if ((bool)mo["ipEnabled"])
                {
                    if (mo["Caption"].Equals(nicName))
                    {
                        IPAddress = (string[])mo["IPAddress"];

                        break;
                    }
                }
            }

            return IPAddress;
        }

        public static string[] GetIPSubnetAddress(string nicName)
        {
            string[] IPSubnetAddress = null;

            ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection moc = mc.GetInstances();

            foreach (ManagementObject mo in moc)
            {
                // Make sure this is a IP enabled device. Not something like memory card or VM Ware
                if ((bool)mo["ipEnabled"])
                {
                    if (mo["Caption"].Equals(nicName))
                    {
                        IPSubnetAddress = (string[])mo["IPSubnet"];

                        break;
                    }
                }
            }

            return IPSubnetAddress;
        }

        public static string[] GetDefaultIPGatewayAddress(string nicName)
        {
            string[] DefaultIPGatewayAddress = null;

            ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection moc = mc.GetInstances();

            foreach (ManagementObject mo in moc)
            {
                // Make sure this is a IP enabled device. Not something like memory card or VM Ware
                if ((bool)mo["ipEnabled"])
                {
                    if (mo["Caption"].Equals(nicName))
                    {
                        DefaultIPGatewayAddress = (string[])mo["DefaultIPGateway"];
                    }
                }
            }

            return DefaultIPGatewayAddress;
        }

        public static string[] GetDNSServerAddress(string nicName)
        {
            string[] DNSServerAddress = null;

            ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection moc = mc.GetInstances();

            foreach (ManagementObject mo in moc)
            {
                // Make sure this is a IP enabled device. Not something like memory card or VM Ware
                if ((bool)mo["ipEnabled"])
                {
                    if (mo["Caption"].Equals(nicName))
                    {
                        DNSServerAddress = (string[])mo["DNSServerSearchOrder"];
                        break;
                    }
                }
            }

            return DNSServerAddress;
        }

        public static bool DHCPEnabled(string nicName)
        {
            ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection moc = mc.GetInstances();

            foreach (ManagementObject mo in moc)
            {
                // Make sure this is a IP enabled device. Not something like memory card or VM Ware
                if ((bool)mo["ipEnabled"])
                {
                    if (mo["Caption"].Equals(nicName))
                    {
                        try
                        {
                            if ((bool)mo["DHCPEnabled"])
                            {
                                //MessageBox.Show("[TEST] -- NetworkManagement -- DHCPEnabled(string) -- DHCPEnable! -- succcc!");
                                return true;
                            }
                        }
                        catch (NullReferenceException e)
                        {
                            MessageBox.Show("[Error]: Could not get DHCP settings Infomation!\r\n" + e.Message);
                        }
                    }
                }
            }

            return false;
        }

        /// <summary>
        /// Returns the list of Network Interfaces installed
        /// </summary>
        /// <returns>Array list of string</returns>
        public static ArrayList GetNICNames()
        {
            ArrayList nicNames = new ArrayList();

            ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection moc = mc.GetInstances();

            foreach (ManagementObject mo in moc)
            {
                if ((bool)mo["ipEnabled"])
                {
                    nicNames.Add(mo["Caption"]);
                }
            }

            return nicNames;
        }

        public static string GetMACAddress(string nicName)
        {
            string MACAddress = null;

            ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection moc = mc.GetInstances();

            foreach (ManagementObject mo in moc)
            {
                // Make sure this is a IP enabled device. Not something like memory card or VM Ware
                if ((bool)mo["ipEnabled"])
                {
                    if (mo["Caption"].Equals(nicName))
                    {
                        MACAddress = (string)mo["MACAddress"];

                        break;
                    }
                }
            }

            return MACAddress;
        }

        #endregion

    }


}
